﻿using System.Xml.Serialization;
using System.IO;
using System.Diagnostics;

namespace DotNet.Common
{
	public class XMLConfig<DataType>
		where DataType : new()
	{
		public delegate void DataInvoker(bool result,DataType data);
		
		XmlSerializer m_ser;
		string m_filename;
		DataType m_data;

		public event DataInvoker Loaded;
		public event VoidInvoker Created;
		public event VoidInvoker Unloaded;
		public event VoidInvoker Saved;

		public DataType Data
		{
			get { return m_data; }
			set { m_data = value; }
		}

		public string FileName
		{
			get { return m_filename; }
		}
		
		public XMLConfig()
		{
			m_ser = new XmlSerializer(typeof(DataType));
		}

		public bool Load(string filename)
		{
            Debug.Assert(Path.IsPathRooted(filename));

			bool result = LoadFile(filename);

			if (Loaded != null)
				Loaded(result,m_data);

			return result;
		}

		bool LoadFile(string filename)
		{
			if (string.IsNullOrEmpty(filename))
			{
				m_data = new DataType();
				return false;
			}

			if (!File.Exists(filename))
			{
				m_filename = filename;
				m_data = new DataType();
				return false;
			}

			if (m_filename != null && string.Compare(m_filename, filename, true) != 0)
			{
				Save();
			}

			try
			{
				m_filename = filename;
				using (Stream file = new FileStream(m_filename, FileMode.Open, FileAccess.Read))
				{
					m_data = (DataType)m_ser.Deserialize(file);
					file.Close();
				}
				return true;
			}
			catch
			{
				m_data = new DataType();
				return false;
			}
		}

		public bool Create(string filename)
		{
			if (string.Compare(m_filename, filename, true) != 0)
				Save();

			m_filename = filename;
			m_data = new DataType();

			if (Created != null)
				Created();

			return Save();
		}

		public bool Save()
		{
			try
			{
				if (!string.IsNullOrEmpty(m_filename))
				{
					using (Stream file = new FileStream(m_filename, FileMode.Create, FileAccess.Write))
					{
						m_ser.Serialize(file, m_data);
						file.Close();
					}

					if (Saved != null)
						Saved();

					return true;
				}
				else
				{
					return false;
				}
			}
			catch
			{
				return false;
			}
		}

        public bool Save(string filename,DataType data)
        {
            m_filename = filename;
            m_data = data;

            return Save();
        }

        public bool Save(string filename)
        {
            m_filename = filename;

            return Save();
        }

		public void Unload()
		{
			Save();

			if (Unloaded != null)
				Unloaded();

			m_filename = string.Empty;
			m_data = new DataType();
		}
	}
}
